package com.sort;

import java.util.Arrays;

/**
 * 插入排序的优化，希尔排序
 * 作者：swk
 * 时间：
 * 公司：
 **/
public class ShellSort {
    public static long count = 0;
    private static int count2 = 0;

    public static void main(String[] args) {
        int[] arr = new int[80000];
        for (int i = 0; i < 80000; i++) {
            arr[i] = (int) (Math.random() * 8000000);
        }
        long beginTime = System.currentTimeMillis();
        shellSort(arr);
        long endTime = System.currentTimeMillis();
       // System.out.println("排序后结果：" + Arrays.toString(arr));
        System.out.println("耗时：" + (endTime - beginTime));
        System.out.println("循环次数：" + count);
        count = 0;

        System.out.println("-------------------------------------------");
        int[] arr2 = new int[800000];
        for (int i = 0; i < 800000; i++) {
            arr2[i] = (int) (Math.random() * 8000000);
        }
        long beginTime2 = System.currentTimeMillis();
        shellSort2(arr2);
        long endTime2 = System.currentTimeMillis();
        //System.out.println("排序后结果：" + Arrays.toString(arr));
        System.out.println("移动法希尔排序耗时：" + (endTime2 - beginTime2));
        System.out.println("循环次数：" + count2);
        count2 = 0;
    }

    public static void shellSort(int[] arr) {
        int temp = 0;
        //根据前面的逐步分析，使用循环处理
        for (int gap = arr.length / 2; gap > 0; gap /= 2) {
            for (int i = gap; i < arr.length; i++) {
                // 遍历各组中所有的元素(共5组，每组有2个元素)，步长5
                for (int j = i - gap; j >= 0; j -= gap) {
                    // 如果当前元素大于加上步长后的那个元素，说明交换
                    if (arr[j] > arr[j + gap]) {
                        temp = arr[j];
                        arr[j] = arr[j + gap];
                        arr[j + gap] = temp;
                    }
                    count++;
                }
            }
        }
    }

    //对交换式的希尔排序进行优化->移位法
    public static void shellSort2(int[] arr) {
        // 增量gap，并逐步的缩小增量
        for (int gap = arr.length / 2; gap > 0; gap /= 2) {
            // 从第gap个元素，逐个对其所在的组进行直接插入排序
            for (int i = gap; i < arr.length; i++) {
                int j = i;
                int temp = arr[j];
                if (arr[j] < arr[j - gap]) {
                    while (j - gap >= 0 && temp < arr[j - gap]) {//移动
                        arr[j] = arr[j - gap];
                        j -= gap;
                        count2++;
                    }
                    //当退出while后，就给temp找到插入的位置
                    arr[j] = temp;
                }
            }
        }
    }
}
